/*
 * main.c
 *
 *  Created on: 27.11.2011
 *      Author: alexs
 */

#include "stm32f10x.h"
#include "stm32f10x_it.h"
#include "stm32f10x_conf.h"
//#include <stdio.h>
#include <stdlib.h>
#include "prn_func.h"
#include <string.h>
#include "main.h"
#include "rfm23.h"

#define LED_ON GPIO_ResetBits(GPIOA,GPIO_Pin_8)
#define LED_OFF GPIO_SetBits(GPIOA,GPIO_Pin_8)

const uint32_t arr26[]={CHIP26_0,CHIP26_1,CHIP26_2};
const uint32_t arr27[]={CHIP27_0,CHIP27_1,CHIP27_2};
uint32_t chip_SN[3];
uint8_t chip_tx=0;

char USART_TX_BUFF[USART_TX_BUFF_SIZE];
volatile uint8_t timeout_flag=0;
uint32_t psent=0;
uint32_t perr=0;
uint32_t pointerr=0;

volatile uint16_t tHigh;

void HW_init();
uint8_t SPI_talk(SPI_dir dir, const uint8_t addr, const uint8_t val);

point_t points_arr[NUM_POINTS];

int main() {
	RCC_ClocksTypeDef clocks;
	uint8_t rndv=0;
	uint32_t * uid;
	uint8_t i,j,err;
	uint8_t * p8;
	uint8_t darr[POINTS_SIZE];
	char * nextline;
	char nonext[]="";
	char tonext[]="\n";


	HW_init();
	RCC_GetClocksFreq(&clocks);

	DBGuld("Hi Alex! ",clocks.PCLK2_Frequency,"\r\n!!!\r\n");

	uid=(uint32_t *)(0x1FFFF7E8);
	chip_SN[2]=*(uid++);
	chip_SN[1]=*(uid++);
	chip_SN[0]=*uid;

	if (memcmp(chip_SN,arr27,sizeof(chip_SN))==0) {
		DBGstr("Slave chip\r\n");
	}
	else if (memcmp(chip_SN,arr26,sizeof(chip_SN))==0) {
		DBGstr("Master chip\r\n");
		chip_tx=1;
	}
	else {
		DBGstr("Chip unknown!\r\n");
		DBGulh("SN2 0x",chip_SN[2],"\r\n");
		DBGulh("SN1 0x",chip_SN[1],"\r\n");
		DBGulh("SN0 0x",chip_SN[0],"\r\n");
	}
	TIM_Cmd(TIM4,ENABLE);
	while (!timeout_flag);
	timeout_flag=0;
	SPI_talk(WRITE,RFM23_07_Operating_Mode_and_Function_Control_1,0x80);
	TIM_Cmd(TIM4,ENABLE);
	while (!timeout_flag);
	timeout_flag=0;

	RFM23_Init(1);
	RFM23_to_READY();

	rndv=0;
	j=0;
	for (;;){

		if (chip_tx) {
			for (i=0;i<NUM_POINTS;i++) {
				points_arr[i].point_name=i+1;
				points_arr[i].current_point=i+1;
				points_arr[i].total_points=NUM_POINTS;
				//		DBGuld("Name > ",points_arr[i].point_name,"");
				points_arr[i].point_time=rand();
				//		DBGuld(" time > ",points_arr[i].point_time,"");
				points_arr[i].point_lat=rand();
				//		DBGuld(" lat > ",points_arr[i].point_lat,"");
				points_arr[i].point_lon=rand();
				//		DBGuld(" lon > ",points_arr[i].point_lon,"\r\n");
			}
			psent++;
			SPI_talk(WRITE,RFM23_3A_Transmit_Header_3,((psent&0xff000000)>>24));
			SPI_talk(WRITE,RFM23_3B_Transmit_Header_2,((psent&0x00ff0000)>>16));
			SPI_talk(WRITE,RFM23_3C_Transmit_Header_1,((psent&0x0000ff00)>>8));
			SPI_talk(WRITE,RFM23_3D_Transmit_Header_0,((psent&0x000000ff)));
			LED_ON;
			TIM_SetCounter(TIM1,0);
			tHigh=0;
			TIM_Cmd(TIM1,ENABLE);
			for (j=0;j<NUM_POINTS;j++) {
				p8=(uint8_t *)&points_arr[j];
				RFM23_clear_tx();
				SPI_talk(WRITE,RFM23_3E_Packet_Length,POINTS_SIZE);
				for (i=0;i<POINTS_SIZE;i++) {
					//					darr[i]=*p8;
					RFM23_push(*p8);
					//					rndv++;
				}
				//			DBGulh("Send 0x",rndv-1,"\r\n");
				RFM23_set_TXINT();
				RFM23_clear_intterrupt();
				//			while (!NIRQ_stat());
				RFM23_to_TX();
				while (NIRQ_stat());
				RFM23_to_READY();
			}
			TIM_Cmd(TIM1,DISABLE);
			DBGuld(" Timer ",(((uint32_t)tHigh)<<16)|TIM_GetCounter(TIM1),"\r");
			LED_OFF;
			TIM_Cmd(TIM4,ENABLE);
			while (!timeout_flag);
			timeout_flag=0;
			/*
			psent++;
			SPI_talk(WRITE,RFM23_7E_RX_FIFO_Control,POINTS_SIZE+HEADER_SIZE);
			RFM23_clear_rx();
			RFM23_to_RX();
			RFM23_set_RXINT();
			RFM23_clear_intterrupt();
			TIM_SetCounter(TIM4,0);
			timeout_flag=0;
			TIM_Cmd(TIM4,ENABLE);
			nextline=nonext;
			while ((NIRQ_stat())&&(!timeout_flag));
			TIM_Cmd(TIM4,DISABLE);
			if (NIRQ_stat()) {
				//ERROR
				//				DBGstr("Error\r\n");
				perr++;
				nextline=tonext;
			}else{
				//OK
				err=0;
				for (i=0;i<(POINTS_SIZE+HEADER_SIZE);i++) {
					if (i>(HEADER_SIZE-1)) {
						if (darr[i-HEADER_SIZE]!=RFM23_pop()) err=1;
					}else{
						RFM23_pop();
					}
				}
				if (!err) {
					//DBGstr("Ok\r\n");
				}else{
					//ERROR
					perr++;
					nextline=tonext;
				}
			}
			i=SPI_talk(READ,RFM23_26_Received_Signal_Strength_Indicator,0);
			DBGuld(" Send ",psent," packets.");
			DBGuld(" Lost ",perr," packets.");
			DBGuld(" RSSI ",i,"     \r");
			 */
			//			DBGstr(nextline);
		}else{
			//			SPI_talk(WRITE,RFM23_3E_Packet_Length,0);
			SPI_talk(WRITE,RFM23_7E_RX_FIFO_Control,POINTS_SIZE+HEADER_SIZE);
			RFM23_clear_rx();
			RFM23_to_RX();
			RFM23_set_RXINT();
			RFM23_clear_intterrupt();
			LED_OFF;
			//			while (!NIRQ_stat());
			while (NIRQ_stat());
			LED_ON;
			uint32_t tmp=0;
			for (i=0;i<(POINTS_SIZE+HEADER_SIZE);i++) {
				if (i>3) {
					RFM23_pop();
				}
				else {
					tmp<<=8;
					tmp+=RFM23_pop();
				}
			}
			if ((tmp-psent)>1) {
				//пропущен большой пакет
				if (j<60) pointerr+=60-j;
				perr+=tmp-psent-1;
				psent=tmp;
				j=1;
				DBGuld(" Rec ",psent," packet, ");
				DBGuld("packet error: ",perr," ");
				DBGuld("point error: ",pointerr," ");
				rndv=SPI_talk(READ,RFM23_26_Received_Signal_Strength_Indicator,0);
				DBGuld("RSSI >> ",rndv,"           \r");
			}else if ((tmp-psent)>0) {
				//new packet посчитать кол-во точек
				if (j<60) pointerr+=60-j;
				psent=tmp;
				j=1;
				DBGuld(" Rec ",psent," packet, ");
				DBGuld("packet error: ",perr," ");
				DBGuld("point error: ",pointerr," ");
				rndv=SPI_talk(READ,RFM23_26_Received_Signal_Strength_Indicator,0);
				DBGuld("RSSI >> ",rndv,"           \r");
			}else{
				j++;
			}
		}
	}
	return 0;
}

void HW_init(){
	GPIO_InitTypeDef gpio_init_stuct;
	USART_InitTypeDef usart_init_struct;
	USART_ClockInitTypeDef usartck_init_struct;
	DMA_InitTypeDef dma_init_struct;
	SPI_InitTypeDef spi_init_struct;
	TIM_TimeBaseInitTypeDef time_base_init_struct;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
	RCC_APB2PeriphClockCmd(
			RCC_APB2Periph_AFIO|
			RCC_APB2Periph_GPIOA|
			RCC_APB2Periph_GPIOB|
			RCC_APB2Periph_USART1|
			RCC_APB2Periph_SPI1|
			RCC_APB2Periph_TIM1
			,ENABLE);
	RCC_APB1PeriphClockCmd(
			RCC_APB1Periph_USART2|
			RCC_APB1Periph_TIM4
			,ENABLE);

	/*Светодиод*/
	gpio_init_stuct.GPIO_Mode=GPIO_Mode_Out_OD;
	gpio_init_stuct.GPIO_Pin=GPIO_Pin_8;
	gpio_init_stuct.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_Init(GPIOA,&gpio_init_stuct);

	/*USART TX*/
	gpio_init_stuct.GPIO_Mode=GPIO_Mode_AF_PP;
	gpio_init_stuct.GPIO_Pin=GPIO_Pin_2;
	gpio_init_stuct.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_Init(GPIOA,&gpio_init_stuct);

	/*USART RX*/
	gpio_init_stuct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	gpio_init_stuct.GPIO_Pin=GPIO_Pin_3;
	gpio_init_stuct.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_Init(GPIOA,&gpio_init_stuct);

	/*SPI: CLK MOSI NSS */
	gpio_init_stuct.GPIO_Mode=GPIO_Mode_AF_PP;
	gpio_init_stuct.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_7;
	gpio_init_stuct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&gpio_init_stuct);

	GPIO_SetBits(GPIOA,GPIO_Pin_4);
	gpio_init_stuct.GPIO_Mode=GPIO_Mode_Out_PP;
	gpio_init_stuct.GPIO_Pin=GPIO_Pin_4;
	gpio_init_stuct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&gpio_init_stuct);

	/*SPI MISO*/
	gpio_init_stuct.GPIO_Mode=GPIO_Mode_IPU;
	gpio_init_stuct.GPIO_Pin=GPIO_Pin_6;
	gpio_init_stuct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&gpio_init_stuct);

	/*SPI nIRQ*/
	gpio_init_stuct.GPIO_Mode=GPIO_Mode_IPU;
	gpio_init_stuct.GPIO_Pin=GPIO_Pin_0;
	gpio_init_stuct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&gpio_init_stuct);

	/*USART*/
	//	USART_StructInit(&usart_init_struct);
	usart_init_struct.USART_BaudRate=115200UL;
	usart_init_struct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	usart_init_struct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
	usart_init_struct.USART_Parity=USART_Parity_No;
	usart_init_struct.USART_StopBits=USART_StopBits_1;
	usart_init_struct.USART_WordLength=USART_WordLength_8b;
	USART_Init(USART2,&usart_init_struct);
	USART_ClockStructInit(&usartck_init_struct);
	USART_ClockInit(USART2,&usartck_init_struct);


	/*DMA-USART*/
	dma_init_struct.DMA_MemoryBaseAddr=(uint32_t)USART_TX_BUFF;
	dma_init_struct.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
	dma_init_struct.DMA_MemoryInc=DMA_MemoryInc_Enable;
	dma_init_struct.DMA_Mode=DMA_Mode_Normal;
	dma_init_struct.DMA_BufferSize=0;
	dma_init_struct.DMA_DIR=DMA_DIR_PeripheralDST;
	dma_init_struct.DMA_M2M=DMA_M2M_Disable;
	dma_init_struct.DMA_Priority=DMA_Priority_High;
	dma_init_struct.DMA_PeripheralBaseAddr=USART2_BASE+0x04;
	dma_init_struct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
	dma_init_struct.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
	DMA_Init(USART2TXDMA,&dma_init_struct);
	DMA_ClearFlag(USART2TCFLAG);
	USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE);
	//	DMA_Cmd(DMA1_Channel7,ENABLE);
	USART_Cmd(USART2,ENABLE);

	/*SPI*/
	spi_init_struct.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_16;
	spi_init_struct.SPI_CPHA=SPI_CPHA_1Edge;
	spi_init_struct.SPI_CPOL=SPI_CPOL_Low;
	spi_init_struct.SPI_CRCPolynomial=7;
	spi_init_struct.SPI_DataSize=SPI_DataSize_16b;
	spi_init_struct.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
	spi_init_struct.SPI_FirstBit=SPI_FirstBit_MSB;
	spi_init_struct.SPI_Mode=SPI_Mode_Master;
	spi_init_struct.SPI_NSS=SPI_NSS_Soft;
	SPI_Init(SPI1,&spi_init_struct);
	//	SPI_DataSizeConfig(SPI1,SPI_DataSize_16b);
	//	SPI_SSOutputCmd(SPI1,ENABLE);
	SPI_Cmd(SPI1,ENABLE);

	/*1 sec timer*/
	NVIC_SetVectorTable(NVIC_VectTab_FLASH,0);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

	NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=15;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	time_base_init_struct.TIM_ClockDivision=TIM_CKD_DIV1;
	time_base_init_struct.TIM_CounterMode=TIM_CounterMode_Up;
	time_base_init_struct.TIM_Period=36000;
	time_base_init_struct.TIM_Prescaler=200;
	time_base_init_struct.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM4,&time_base_init_struct);
	TIM_ARRPreloadConfig(TIM4,ENABLE);
	TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
	//	TIM_Cmd(TIM4,ENABLE);

	NVIC_InitStructure.NVIC_IRQChannel=TIM1_UP_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=15;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	time_base_init_struct.TIM_ClockDivision=TIM_CKD_DIV1;
	time_base_init_struct.TIM_CounterMode=TIM_CounterMode_Up;
	time_base_init_struct.TIM_Period=0xffff;
	time_base_init_struct.TIM_Prescaler=0;
	time_base_init_struct.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM1,&time_base_init_struct);
	TIM_ARRPreloadConfig(TIM1,ENABLE);
	TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);

}

void TIM4_IRQHandler(void) {
	TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
	timeout_flag=1;
	TIM_Cmd(TIM4,DISABLE);
}
void TIM1_UP_IRQHandler(void) {
	TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
	tHigh++;
}

caddr_t _sbrk(int incr)
{
	extern char _ebss;
	static char *heap_end;
	char *prev_heap_end;

	if (heap_end == 0)
	{
		heap_end = &_ebss;
	}
	prev_heap_end = heap_end;

	char * stack = (char*) __get_MSP();
	if (heap_end + incr > stack)
	{
		//        _write(STDERR_FILENO, "Heap and stack collision\n", 25);
		errno = ENOMEM;
		return (caddr_t) -1;
		//abort ();
	}

	heap_end += incr;
	return (caddr_t) prev_heap_end;

}
